import 'package:audioplayers/audioplayers.dart';

final AudioPlayer _player = AudioPlayer();
final Player player = AllPlatformPlayer();

final AllPlatformPlayService playService = AllPlatformPlayService();

enum CurrentPlayerState { Play, Pause, Stop, Completed }

class AllPlatformPlayer extends Player {
  @override
  void play(String urlSouce) {
    _player.play(UrlSource(urlSouce));
  }

  @override
  void stop() {
    _player.stop();
  }

  @override
  void pause() {
    _player.pause();
  }

  @override
  void resume() {
    _player.resume();
  }

  @override
  bool isPuase() {
    return playService.state() == CurrentPlayerState.Pause;
  }

  @override
  bool isPlaying() {
    return playService.state() == CurrentPlayerState.Play;
  }

  @override
  void seek(Duration d) {
    _player.seek(d);
  }
}

abstract class Player {
  bool isPuase();

  bool isPlaying();

  void play(String urlSource);

  void stop();

  void resume();

  void pause();

  void seek(Duration d);
}

abstract class IPlayService {
  void play(String sourceUrl);

  CurrentPlayerState state();

  void seek(Duration d);
}

class AllPlatformPlayService extends IPlayService {
  Stream<void> get onPlayerComplete => _player.onPlayerComplete;

  Stream<Duration> get onDurationChanged => _player.onDurationChanged;

  Stream<Duration> get onPositionChanged => _player.onPositionChanged;

  Stream<CurrentPlayerState> get onPlayerStateChanged {
    return _player.onPlayerStateChanged.map((e) {
      switch (e) {
        case PlayerState.stopped:
          return CurrentPlayerState.Stop;
        case PlayerState.playing:
          return CurrentPlayerState.Play;
        case PlayerState.paused:
          return CurrentPlayerState.Pause;
        case PlayerState.completed:
          return CurrentPlayerState.Completed;
        case PlayerState.disposed:
          return CurrentPlayerState.Stop;
      }
    });
  }

  @override
  void play(String sourceUrl) {
    if (state() == CurrentPlayerState.Play) {
      player.stop();
    }
    // _player.onDurationChanged
    player.play(sourceUrl);
  }

  @override
  CurrentPlayerState state() {
    CurrentPlayerState s = CurrentPlayerState.Stop;
    switch (_player.state) {
      case PlayerState.playing:
        s = CurrentPlayerState.Play;
        break;
      case PlayerState.stopped:
        s = CurrentPlayerState.Stop;
        break;
      case PlayerState.paused:
        s = CurrentPlayerState.Pause;
        break;
      case PlayerState.completed:
        s = CurrentPlayerState.Completed;
        break;
      case PlayerState.disposed:
        s = CurrentPlayerState.Stop;
        break;
    }
    return s;
  }

  @override
  void seek(Duration d) {
    player.seek(d);
  }
}
